from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.by import By

from common.decorators import log4gs
from common.functions import has_text_wait


LOCATOR_LIST = {
    'css': By.CSS_SELECTOR,
    'id_': By.ID,
    'name': By.NAME,
    'xpath': By.XPATH,
    'link_text': By.LINK_TEXT,
    'partial_link_text': By.PARTIAL_LINK_TEXT,
    'tag': By.TAG_NAME,
    'class_name': By.CLASS_NAME,
}


@log4gs
class VueElement(WebElement):
    """通过id、name、class_name、css、xpath、link_text、partial_link_text、tag来定位单个元"""

    def __init__(self, describe=None, **kwargs):
        """
        :param describe: 目标元素描述
        :param kwargs: 定位器

        使用方法：
        ele1 = VueElement(id='app')
        ele2 = VueElement(tag='h1')
        """
        self.describe = describe
        if not kwargs or len(kwargs) > 1:
            try:
                raise ValueError("必须且只提供一种定位方式")
            except ValueError:
                self.log.error("必须且只提供一种定位方式")

        try:
            self.by, self.value = next(iter(kwargs.items()))
            self.by = LOCATOR_LIST[self.by]
        except KeyError:
            self.log.error("请用一种正确的定位方式：id、name、class_name、css、xpath、link_text、partial_link_text、tag")

    def __get__(self, instance, owner):
        self.driver = instance.driver
        try:
            return instance.supply.find_element(by=self.by, value=self.value)   # supply协议
        except Exception:
            self.log.error("通过定位器：’{}：{}‘没有找到元素".format(self.by, self.value))


@log4gs
class VueElements(WebElement):
    """通过id、name、class_name、css、xpath、link_text、partial_link_text、tag来定位多个元素，返回指定元素"""

    def __init__(self, index=None, text=None, describe=None, **kwargs):
        """
        :param index: 目标元素在找出的所有元素中的序号
        :param text: 目标元素的文本内容（去空格后）
        :param describe: 目标元素描述
        :param kwargs: 定位器

        使用方法：
        ele1 = VueElement(class_name='ivu-check-box', index=3)   # 类名是ivu-check-box的第三个元素
        ele2 = VueElement(tag='li', text="标签信息")   # text是“标签信息”的li元素
        """
        self.ele_index = index
        self.ele_text = text
        self.describe = describe
        if not kwargs or len(kwargs) > 1:
            try:
                raise ValueError("必须且只提供一种定位方式")
            except ValueError:
                self.log.error("必须且只提供一种定位方式")

        try:
            self.by, self.value = next(iter(kwargs.items()))
            self.by = LOCATOR_LIST[self.by]
        except KeyError:
            self.log.error("请用一种正确的定位方式：id、name、class_name、css、xpath、link_text、partial_link_text、tag")

        if not text and not index and index != 0:
            try:
                raise ValueError("文本内容和序号至少提供一个")
            except ValueError:
                self.log.error("文本内容和序号至少提供一个", exc_info=True)

    def __get__(self, instance, owner):
        self.driver = instance.driver
        try:
            elements = instance.supply.find_elements(by=self.by, value=self.value)  # supply协议
            if self.ele_index or self.ele_index == 0:
                try:
                    return elements[self.ele_index]
                except Exception:
                    self.log.error("通过序号{}没有找到元素".format(self.ele_index))
            else:
                for element in elements:
                    text = element.text.strip().replace(' ', '')
                    if text == self.ele_text:
                        return element
                try:
                    raise Exception
                except Exception:
                    self.log.error("通过文本内容：{}没有找到元素".format(self.ele_text))
        except Exception:
            self.log.error("通过定位器：'{}：{}'没有找到元素".format(self.by, self.value))